#include "RedSocial.h"

void RedSocial::registrar(Usuario u, Pais p){
    InfoUsuario* i = new InfoUsuario(p);
	usuarios.definir(u,i);
}

const bool RedSocial::sonAmigos(const Usuario u1, const Usuario u2) const{
    InfoUsuario::ItListaInfoUsuario it = (usuarios.obtener(u1)).CrearItAmigos();
    InfoUsuario* buscado;
    bool res = false;

    buscado = &(usuarios.obtener(u2));
    while(it.HayMas()){
        res = res || it.Actual() == buscado;
        it.Avanzar();
    }

    return res;
}

const bool RedSocial::quiereSerAmigo(const Usuario u1, const Usuario u2) const{
    InfoUsuario& infou1 = usuarios.obtener(u1);
    return infou1.envioSolicitud(u2);
}

void RedSocial::publicar(Mensaje* m){
	InfoUsuario::ItListaInfoUsuario it1;
	Conj<Tag>::const_Iterador it2;
	InfoUsuario& infoAutor = usuarios.obtener(m->usuario);
	mensajes.insertar(m);
	infoAutor.agregarPublicado(m);
	it1 = infoAutor.CrearItAmigos();
	it2 = (m->tags).CrearIt();

	while (it1.HayMas()) {
		if (reglas.puedeVer(it1.Actual()->paisDe(), infoAutor.paisDe())) {
				(it1.Actual())-> agregarVisible(m);
			}
		it1.Avanzar();
	}

	while (it2.HaySiguiente()){
        contabilizarTag(it2.Siguiente());
		it2.Avanzar();
    }

}

void RedSocial::quererSerAmigo(Usuario u1, Usuario u2){
	InfoUsuario& infoUsuario1 = usuarios.obtener(u1);
	InfoUsuario& infoUsuario2 = usuarios.obtener(u2);
	if(infoUsuario2.envioSolicitud(u1)){
		infoUsuario2.borrarSolicitud(u1);
		infoUsuario1.agregarAmigo(&infoUsuario2);
		infoUsuario2.agregarAmigo(&infoUsuario1);
		if(reglas.puedeVer(infoUsuario2.paisDe(), infoUsuario1.paisDe())){
			infoUsuario2.actualizarVisibles(&infoUsuario1);
		}
		if(reglas.puedeVer(infoUsuario1.paisDe(), infoUsuario2.paisDe())) {
			infoUsuario1.actualizarVisibles(&infoUsuario2);
		}
	}else{
		infoUsuario1.agregarSolicitud(u2);
	}
}

const ListaOrd::ItListaOrd RedSocial::mensajesVisibles(Usuario u) const {
	return (usuarios.obtener(u)).CrearItVisibles();
}

const ListaOrd::ItListaTemp RedSocial::mensajesVisiblesRecientes(Usuario u) const{
	return (usuarios.obtener(u)).CrearItVisiblesRecientes();
}

aed2::Nat RedSocial::repeticionesRecientesTag(Tag t){
	Arreglo<RedSocial::Sig> semana(7);
	aed2::Nat acum = 0;
	semana = (this -> tags).dicc.obtener(t);
    for(int i=0; i<7; i++){
        if( (semana[i].fecha).mismaSemana(this->fechaActual()) ){
            acum = (acum+semana[i].reps);
        }

    }
	return acum;
}


Fecha RedSocial::fechaActual(){
	return (mensajes.CrearItListaOrd().Actual()->creado);
}

/*Iterador magico :D*/

RedSocial::ItListaTags::ItListaTags() : it() {}

RedSocial::ItListaTags RedSocial::CrearItTags(){
	return ItListaTags(*this);
}

RedSocial::ItListaTags::ItListaTags(RedSocial& rs) : it(rs.tags.claves){
    crs = &rs;
    Tag t;
    //std::cout << "Empieza" << rs.tags.claves << std::endl;
    while( it.hayMas() && crs->repeticionesRecientesTag(it.actual()) == 0 ){
        it.avanzar();
    }
}

bool RedSocial::ItListaTags::hayMas() const{
    bool res = false;
    ItUniLista<Tag> todos(it);
    //std::cout << "Empieza" << std::endl;
    while(todos.hayMas() && !res){
        //std::cout << todos.actual() << std::endl;
        res = (crs->repeticionesRecientesTag(todos.actual()) > 0);
        todos.avanzar();
    }
	return res;
}

const Tag RedSocial::ItListaTags::actual() const{
	assert(hayMas());
	return it.actual();
}

void RedSocial::ItListaTags::avanzar(){
	assert(hayMas());
	it.avanzar();
}

void RedSocial::contabilizarTag(Tag t){
	Fecha fechaAct = fechaActual();
	if(tags.dicc.definido(t)){
        Sig& diaSem = tags.dicc.obtener(t)[fechaAct.diaSemana()];

        if(diaSem.fecha.mismoDia(fechaAct)){
            diaSem.reps++;
        }else{
            diaSem.reps = 1;
            diaSem.fecha = fechaAct;
        }
    }else{
        Arreglo<RedSocial::Sig>* semana = new Arreglo<RedSocial::Sig>(7);
        for(int i = 0; i < 7; i++){
            RedSocial::Sig s;
            s.reps = 0;
            s.fecha = Fecha();
            semana->Definir(i, s);
        }
        RedSocial::Sig s;
        s.fecha = fechaAct;
        s.reps = 1;
        semana->Definir(fechaAct.diaSemana(), s);
        tags.claves.AgregarAdelante(t);
        tags.dicc.definir(t, semana);
    }
}

RedSocial::ItListaTags RedSocial::tagsRecientes(){
    return CrearItTags();
}

RedSocial::~RedSocial(){
	ListaOrd::ItListaOrd it = mensajes.CrearItListaOrd();
	while (it.HayMas()){
		delete it.ActualAux();
		it.Avanzar();
	}
}






